#ifndef ICEUDP_H_
#define ICEUDP_H_

#define ICE_CRC32_VALUE 0x5354554e
#define ICE_CRC32_KEY 0xEDB88320
#define ICE_BUFF_LEN 1024
#define ICE_HEADER_LEN 20
#define ICE_TYPE_LEN 2
#define ICE_LEN_LEN 2
#define ICE_USERNAME_BASE 4
#define ICE_FP_LEN 4
#define ICE_MI_LEN 20
#define ICE_MAGICCOOKIE_VALUE 0x2112a442
#define ICE_ATTRI_SLIDE 4
#define ICE_TRANSID_LEN 12
#define ICE_IPV4_LEN 4
#define ICE_IPV6_LEN 16
#define ICE_IPV6_BUF_MAX_LEN 10
#define ICE_IPV6_BYTE_LEN 4

enum Gc_rc
{
  GC_OK = 0,
  GC_MALLOC_ERROR,
  GC_INIT_ERROR,
  GC_RANDOM_ERROR,
  GC_INVALID_CIPHER,
  GC_INVALID_HASH,
  GC_PKCS5_INVALID_ITERATION_COUNT,
  GC_PKCS5_INVALID_DERIVED_KEY_LENGTH,
  GC_PKCS5_DERIVED_KEY_TOO_LONG
};
/*Begin Mod By Huanghao  Cause: ICE New 2014-12-19:13:19:31*/
enum Ice_type
{
    ICE_TYPE_USERNAME = 0x0006,
        ICE_TYPE_MI = 0x0008,
        ICE_TYPE_ERRORCODE = 0x0009,
        ICE_TYPE_UNKNOWNATTRIBUTES = 0x000a,
        ICE_TYPE_XORMAPPEDADDRESS = 0x20,
        ICE_TYPE_PRIORITY = 0x0024,
        ICE_TYPE_USECANDIDATE = 0x0025,
        
        ICE_TYPE_FP = 0x8028,
        ICE_TYPE_CONTROLLED = 0x8029,
        ICE_TYPE_CONTROLLING = 0x802a
};
/*End Mod By Huanghao*/
typedef enum Gc_rc Gc_rc;

/*Begin Add By Huanghao  Cause: ICE New 2014-12-19:13:12:22*/
enum Ice_attribute_flag
{
    ICE_ATTRIBUTE_USERNAME = 1,
        ICE_ATTRIBUTE_ICECONTROLLING = 2,
        ICE_ATTRIBUTE_ICECONTROLLED = 4,
        ICE_ATTRIBUTE_PRIORITY = 8,
        ICE_ATTRIBUTE_USECANDIDATE = 16,
        ICE_ATTRIBUTE_XORMAPPEDADDRESS = 32,
        ICE_ATTRIBUTE_ERRORCODE = 64,
        ICE_ATTRIBUTE_UNKNOWNATTRI = 128,
        ICE_ATTRIBUTE_MI = 256,
        ICE_ATTRIBUTE_FP = 512,
        ICE_ATTRIBUTE_IND_DEFAULT = 512,
        ICE_ATTRIBUTE_ERRRESP_DEFAULT = 576,
        ICE_ATTRIBUTE_REQ_DEFAULT = 795,
        ICE_ATTRIBUTE_RESP_DEFAULT = 800
};
typedef struct StunMessage_Req_tg
{
    char userName[513];
    char iceControlling[8];
    char iceControlled[8];
    unsigned int priority;
}stStunMessageReq;

typedef struct XORMAPADDRESS_tg
{
    char flag; /*should be set 0*/
    char family;
    unsigned short xport;
    union
    {
        unsigned int ipv4xaddress;
        char ipv6xaddress[16];
    };
}stXORMAPADDRESS;

typedef struct ERRORCODE_tg
{
    unsigned short Reserved1; /*should be set 0*/
    unsigned char Reserved2:5; /*should be set 0*/
    unsigned char mClass:3; /*3-6*/
    unsigned short number;  /*0-99*/
    char reasonPhrase[128];
}stERRORCODE;

typedef struct UNKNOWNATTRIBUTES_tg
{
    int typeNum;
    unsigned short type[8];
}stUNKNOWNATTRIBUTES;

typedef struct StunMessage_Resp_tg
{
    stXORMAPADDRESS xorMapAddress;
    
}stStunMessageResp;

typedef struct StunMessage_ErrResp_tg
{
    stERRORCODE errorCode;
    stUNKNOWNATTRIBUTES unknownAttributes;
}stStunMessageErrResp;

typedef struct StunMessage_Ind_tg
{
}stStunMessageInd;

typedef struct StunHeader_tg
{
    unsigned short type;
    unsigned short length;
    unsigned int magicCookie;
    char tranID[12];
}stStunHeader;

typedef struct StunMessage_tg
{
    short attriFlag; /*attribute included, Ice_attribute_flag*/
    char remotePwd[100];
    stStunHeader header;
    union
    {
        stStunMessageReq Req;
        stStunMessageResp Resp;
        stStunMessageErrResp ErrResp;
        stStunMessageInd Ind;
    };
}stStunMsg;

enum Ice_Msg_type
{
    Ice_Msg_Req = 0x0001,
        Ice_Msg_Ind = 0x0011,
        Ice_Msg_Resp = 0x0101,
        Ice_Msg_errResp = 0x0111,
        Ice_Msg_Invalid = 0x1111
};

enum ICE_IP_STATE
{
	ICE_IP_STATE_INIT = 0,
	ICE_IP_STATE_CHAR = 1,
	ICE_IP_STATE_ONEPOINT = 2,
	ICE_IP_STATE_TWOPOINT1 = 3,
	ICE_IP_STATE_TWOPOINT2 = 4,
	ICE_IP_STATE_FOURPOINT = 5
};

enum ICE_IP_MECHANISM_TYPE
{
    ICE_IP_M_TYPE_V4 = 1,
        ICE_IP_M_TYPE_V6 = 2,
        ICE_IP_M_TYPE_V4V6 = 3
};

enum ICE_ERROR_CODE
{
    ICE_SUCCESS = 0,
        ICE_ERR_PARAMETER_ERR = 1,
        ICE_ERR_NOT_STUNMSG =2,
        ICE_ERR_INVALID
};
/*End Add By Huanghao*/

class IcePackage
{
public:
    IcePackage(){};
    virtual ~IcePackage(){};
    int changeIceUserName(char *source, int size, char *buffer);
    int addIceTail(char *icePasswd, char *source, int size, char *buffer);
    int checkIceCommand(char *buf, char* icepwd);
/*Begin Add By Huanghao  Cause: ICE New 2014-12-19:13:00:52*/
    int deleteIceTail(char *icePasswd, char *source, int size, char *buffer);
    bool decodeStunMessage(char *source, int size, stStunMsg *poutStunMsg, int *errCode);
    int createStunMessage(stStunMsg *stMsg, char *pszResult);
    int changePortToX(unsigned short port, unsigned short *xport);
    int changeIpv4AddressToX(unsigned int ip, unsigned int *xip);
    int changeIpv6AddressToX(unsigned char *byteIp, unsigned char *transID, unsigned char *xip);
    int generateRandNum(unsigned char *buff, int len);
    int changeStrIP2BIP(unsigned char *strIp, unsigned char *byteIp);
    int changeStrIpv4AddressToX(unsigned char *strIp, unsigned int *xip);
    int changeStrIpv6AddressToX(unsigned char *strIp, unsigned char *transID, unsigned char *xip);
    bool checkIfStunMsg(char *source, int size);
    int hexatob(char *value, int size, char *result);
    /*int addIceErrorCode();
    int addIceXorMapAddress();
    
    int createIceUserName(char *userName, int size, char *result);*/
/*End Add By Huanghao*/
    
    
private:
    Gc_rc gcHamcSha1(const void *key, size_t keylen,  const void *in, size_t inlen, char *resbuf);
    unsigned int iceCrc32(unsigned char *buf, int len, int *CRC32);
    void iceCrc32Init(int *CRC32);
/*Begin Add By Huanghao  Cause: ICE New 2014-12-19:13:26:33*/
    bool checkStunMsgTypeAvalid(unsigned short type, short attributeFlag);
    int createStunMsgHeader(stStunHeader *pHeader, char *pszResult);
    int createStunMsgReq(stStunMsg *stMsg, char *pszResult);
    int createStunMsgResp(stStunMsg *stMsg, char *pszResult);
    int createStunMsgInd(stStunMsg *stMsg, char *pszResult);
    int createStunMsgErrResp(stStunMsg *stMsg, char *pszResult);
    
    int addUserName(char *source, int size, char *userName, int userNameLen, char *buffer);
    int addControlling(char *source, int size, char *tieBreaker, char *buffer);
    int addControlled(char *source, int size, char *tieBreaker, char *buffer);
    int addPriority(char *source, int size, unsigned int value, char *buffer);
    int addUseCandidate(char *source, int size, char *buffer);
    int addXorMapAddress(char *source, int size, stXORMAPADDRESS *pstXMA, char *buffer);
    int addErroCode(char *source, int size, stERRORCODE *pstEC, char *buffer);
    int addUnknownAttri(char *source, int size, stUNKNOWNATTRIBUTES *pstUA, char *buffer);
    int delIceTailMI(char *icePasswd, char *source, int size, char *buffer);
    int delIceTailFP(char *source, int size, char *buffer);
    unsigned short hexatoi(char *value);
    int changeIPv4ToBIP(unsigned char *strIp, int stateB, int beginP, unsigned char *value, int *column, int *index);
    int getIpv4Value(unsigned char *value, unsigned char *byteIp);
    int getIpv6Value(unsigned char *value, int w, int column, char iptype, unsigned char *byteIp);
/*End Add By Huanghao*/
    int addIceTailMI(char *icePasswd, char *source, int size, char *buffer);
    int addIceTailFP(char *source, int size, char *buffer);

};

#endif